﻿using System;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Acme.Business;
using Acme.Common.Infrastructure;
using Acme.Common.Services;
using Acme.Entities;

namespace Acme.MVVM.IOC
{

    /// <summary>
    /// Depending on your applications requirements, consider performing all data access on anther thread.
    /// Threading Model article: http://msdn.microsoft.com/en-us/library/ms741870.aspx
    /// Parallel Programming in the .NET Framework: http://msdn.microsoft.com/en-us/library/dd460693.aspx
    /// </summary>
    public class MainWindowViewModel : ObservableObject
    {

        #region Declarations

        const String STRING_CONFIRMDELETECAPTION = "Confirm Delete";
        const String STRING_CONFIRMDELETEMESSAGE = "Are you sure you want to DELETE this event?";
        readonly IDialogService _dialog;
        readonly IEventRepository _repository;
        Event _activeEvent;
        ObservableCollection<EventSearchResult> _searchResults;
        EventSearchResult _searchResultSelectedItem;

        #endregion

        #region Properites

        public EventSearchResult SearchResultSelectedItem
        {
            get { return _searchResultSelectedItem; }
            set
            {
                _searchResultSelectedItem = value;
                RaisePropertyChanged("SearchResultSelectedItem");
                RecordSelected(value);
            }
        }

        public ObservableCollection<EventSearchResult> SearchResults
        {
            get { return _searchResults; }
            set
            {
                _searchResults = value;
                RaisePropertyChanged("SearchResults");
            }
        }

        public Event ActiveEvent
        {
            get { return _activeEvent; }
            set
            {
                _activeEvent = value;
                RaisePropertyChanged("ActiveEvent");
            }
        }

        #endregion

        #region Commands

        public ICommand DeleteCommand
        {
            get { return new RelayCommand(DeleteExecute, CanDeleteExecute); }
        }

        public ICommand SaveCommand
        {
            get { return new RelayCommand(SaveExecute, CanSaveExecute); }
        }

        public ICommand CancelCommand
        {
            get { return new RelayCommand(CancelExecute, CanCancelExecute); }
        }

        public ICommand ThrowCommand
        {
            get { return new RelayCommand(ThrowExecute, CanThrowExecute); }
        }

        public ICommand NewCommand
        {
            get { return new RelayCommand(NewExecute); }
        }

        #endregion //Commands

        #region Constructor

        public MainWindowViewModel(IEventRepository repository, IDialogService dialog)
        {
            this._repository = repository;
            this._dialog = dialog;
            LoadSearchResults();
        }

        #endregion //Constructor

        #region Methods

        void LoadSearchResults()
        {
            try
            {
                this.SearchResults = new ObservableCollection<EventSearchResult>(this._repository.GetSearchResults());
            }
            catch (Exception ex)
            {
                this._dialog.ShowException(ex.Message);
            }
        }

        void RecordSelected(EventSearchResult eventSearchResult)
        {
            if (eventSearchResult == null) return;
            try
            {
                this.ActiveEvent = _repository.GetById(eventSearchResult.Id);
            }
            catch (Exception ex)
            {
                this._dialog.ShowException(ex.Message);
            }
        }

        Boolean CanSaveExecute()
        {
            return this.ActiveEvent != null;
        }

        void SaveExecute()
        {
            if (!CanSaveExecute()) return;
            try
            {
                if (_repository.Save(this.ActiveEvent) == 1)
                {
                    ResetForm();
                }
            }
            catch (Exception ex)
            {
                this._dialog.ShowException(ex.Message);
            }
        }

        Boolean CanDeleteExecute()
        {
            return this.ActiveEvent != null;
        }

        void DeleteExecute()
        {
            if (!CanDeleteExecute() || this._dialog.ShowMessage(STRING_CONFIRMDELETEMESSAGE, STRING_CONFIRMDELETECAPTION, DialogButton.OKCancel, DialogImage.Question) != DialogResponse.OK) return;
            try
            {
                _repository.Remove(this.ActiveEvent);
                ResetForm();
            }
            catch (Exception ex)
            {
                this._dialog.ShowException(ex.Message);
            }
        }

        Boolean CanCancelExecute()
        {
            return this.ActiveEvent != null;
        }

        void CancelExecute()
        {
            if (!CanCancelExecute()) return;
            ResetForm();
        }

        Boolean CanThrowExecute()
        {
            return this.ActiveEvent != null;
        }

        void ThrowExecute()
        {
            if (!CanThrowExecute()) return;
            try
            {
                _repository.Save(null);
            }
            catch (Exception ex)
            {
                this._dialog.ShowException(ex.Message);
            }
        }

        void NewExecute()
        {
            this.ActiveEvent = _repository.Create();
            this.SearchResultSelectedItem = null;
        }

        void ResetForm()
        {
            LoadSearchResults();
            this.SearchResultSelectedItem = null;
            this.ActiveEvent = null;
        }

        #endregion //Methods
    }
}
